/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012-2013 Oliver Katz */

#ifndef __ARCH_MODULE_H
#define __ARCH_MODULE_H

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <sstream>

using namespace std;

//namespace sleepyface::arch
namespace sleepyface
{
	namespace arch
	{
		//class ModuleValue: a loosely-typed value for use in modules
		class ModuleValue
		{
		public:
			const static int _uninitialized = -1; //memberof ModuleValue: null type (causes error)
			const static int _bool = 0; //memberof ModuleValue: boolean type
			const static int _int = 1; //memberof ModuleValue: integer type
			const static int _string = 2; //memberof ModuleValue: string type
			const static int _data = 3; //memberof ModuleValue: data (void *) type

		private:
			int type;
			bool b;
			int i;
			string s;
			void *d;

		public:
			ModuleValue(); //methodof ModuleValue: initializer
			ModuleValue(int t, int v); //methodof ModuleValue: initializer from int with type 't'
			ModuleValue(int t, string v); //methodof ModuleValue: initializer from string with type 't'
			ModuleValue(int t, void *v); //methodof ModuleValue: initializer from data with type 't'
			int getType(); //methodof ModuleValue: gets the type
			bool getBool(); //methodof ModuleValue: gets the boolean value
			int getInt(); //methodof ModuleValue: gets the integer value
			string getString(); //methodof ModuleValue: gets the string value
			void *getData(); //methodof ModuleValue: gets the data value
		};

		//class ModuleSignal: a signal to send to a module
		class ModuleSignal
		{
		private:
			int sig;
			vector<ModuleValue> data;

		public:
			ModuleSignal(); //methodof ModuleSignal: initializer
			ModuleSignal(int s); //methodof ModuleSignal: initializer with signal code
			ModuleSignal(int s, vector<ModuleValue> d); //methodof ModuleSignal: initializer with signal code and value arguments
			int append(ModuleValue d); //methodof ModuleSignal: appends a value argument
			int getCode(); //methodof ModuleSignal: gets the signal code
			int size(); //methodof ModuleSignal: gets the number of value arguments
			ModuleValue getData(int idx); //methodof ModuleSignal: gets the value argument at index 'idx'
		};

		class Architecture;

		//class ArchModule: a module to be loaded by the architecture
		class ArchModule
		{
		public:
			const static int signalNull = -1; //memberof ArchModule: null signal (does nothing)
			const static int signalInitialize = 0; //memberof ArchModule: initialization signal
			const static int signalUninitialize = 1; //memberof ArchModule: uninitialization signal
			const static int signalCommandLineArguments = 2; //memberof ArchModule: signal to process command line arguments

			const static int signalLimit = 3; //memberof ArchModule: the lower limit for user-defined signals

		private:
			string name;

		protected:
			bool verbose;

		public:
			ArchModule(); //methodof ArchModule: initializer
			string getName(); //methodof ArchModule: gets the name of the module
			string setName(string n); //methodof ArchModule: sets the name of the module
			void enableVerbose(); //methodof ArchModule: enables verbose output for module
			virtual int signal(ModuleSignal s, Architecture &a); //methodof ArchModule: signal handler
			virtual ModuleValue get(string k0, string k1, Architecture &a); //methodof ArchModule: get handler
			ModuleValue get(string k, Architecture &a); //methodof ArchModule: get handler
			virtual ModuleValue set(string k0, string k1, ModuleValue v, Architecture &a); //methodof ArchModule: set handler
			ModuleValue set(string k, ModuleValue v, Architecture &a); //methodof ArchModule: set handler
			virtual vector<string> list(Architecture &a); //methodof ArchModule: list handler
		};

		//class PluginModule: a dynamically-loaded ArchModule
		class PluginModule : public ArchModule
		{
		public:
			typedef int (*signalCallback)(ModuleSignal*, Architecture*); //memberof PluginModule: signal callback
			typedef ModuleValue *(*getCallback)(char*, char*, Architecture*); //memberof PluginModule: get callback
			typedef ModuleValue *(*setCallback)(char*, char*, ModuleValue*, Architecture*); //memberof PluginModule: set callback
			typedef char **(*listCallback)(Architecture *a); //memberof PluginModule: list callback

		private:
			signalCallback sigc;
			getCallback getc;
			setCallback setc;
			listCallback lsc;

		public:
			int bindSignalCallback(signalCallback c); //memberof PluginModule: bind a signal callback
			int bindGetCallback(getCallback c); //memberof PluginModule: bind a get callback
			int bindSetCallback(setCallback c); //memberof PluginModule: bind a set callback
			int bindListCallback(listCallback c); //memberof PluginModule: bind a list callback

			virtual int signal(ModuleSignal s, Architecture &a); //memberof PluginModule: signal handler
			virtual ModuleValue get(string k0, string k1, Architecture &a); //memberof PluginModule: get handler
			virtual ModuleValue set(string k0, string k1, ModuleValue v, Architecture &a); //memberof PluginModule: set handler
			virtual vector<string> list(Architecture &a); //memberof PluginModule: list handler
		};
	}
}

/// For more information on how to write modules, look at some of the modules under arch/modules. arch/modules/mod_argbuf.{cpp|h} is a good example. 

#endif